package cn.jcet.common.aspect;

import cn.jcet.common.cache.CachePool;
import cn.jcet.module.sys.domain.Dept;
import cn.jcet.module.sys.domain.User;
import cn.jcet.module.sys.vo.DeptVo;
import cn.jcet.module.sys.vo.UserVo;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;

@Aspect
@Component
@EnableAspectJAutoProxy //开启切面代理
public class CacheAspect {

    //private static Logger log = (Logger) LogFactory.getLog(CacheAspect.class);

    /**
     * 声明一个缓存容器
     */
    private Map<String, Object> CACHE_CONTAINER =CachePool.CACHE_CONTAINER;


    /**
     * 部门
     * 声明切面表达式
     */
    private static final String POINTCUT_DEPT_ADD ="execution(* cn.jcet.module.sys.service.impl.DeptServiceImpl.save(..))";

    private static final String POINTCUT_DEPT_UPDATE = "execution(* cn.jcet.module.sys.service.impl.DeptServiceImpl.updateById(..))";

    private static final String POINTCUT_DEPT_GET = "execution(* cn.jcet.module.sys.service.impl.DeptServiceImpl.getOne(..))";

    private static final String POINTCUT_DEPT_DELETE = "execution(* cn.jcet.module.sys.service.impl.DeptServiceImpl.removeById(..))";

    private static final String CACHE_DEPT_PROFIX = "dept:";

    /**
     * 添加
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_DEPT_ADD)
    public Object cacheDeptAdd(ProceedingJoinPoint joinPoint){
        try {
            Dept object = (Dept) joinPoint.getArgs()[0];
            Boolean result = (Boolean) joinPoint.proceed();
            if(result){
                CACHE_CONTAINER.put(CACHE_DEPT_PROFIX+object.getId(),object);
            }
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }


    /**
     * 查询切入
     *
     * @param joinPoint
     * @return
     */
    @Around(value=POINTCUT_DEPT_GET)
    public Object cacheDeptGet(ProceedingJoinPoint joinPoint) {

        try {
            //取出第一个参数
            Integer object = (Integer) joinPoint.getArgs()[0];

            //缓存中取
            Object result1 = CACHE_CONTAINER.get(CACHE_DEPT_PROFIX + object);

            if (result1 != null) {
                return result1;
            } else {
                Dept result2 = (Dept) joinPoint.proceed();
                CACHE_CONTAINER.put(CACHE_DEPT_PROFIX + result2.getId(), result2);
                return result2;
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 更新切入
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_DEPT_UPDATE)
    public Object cacheDeptUpdate(ProceedingJoinPoint joinPoint){
        /**
         * 获取第一个参数
         */
        try {
            DeptVo deptVo = (DeptVo) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if (isSuccess){
                Dept dept= (Dept) CACHE_CONTAINER.get(CACHE_DEPT_PROFIX + deptVo.getId());
                if(null == dept){
                    dept = new Dept();
                    BeanUtils.copyProperties(deptVo,dept);
                    CACHE_CONTAINER.put(CACHE_DEPT_PROFIX+dept.getId(),dept);
                }
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 删除切面
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_DEPT_DELETE)
    public Object cacheDeptDelete(ProceedingJoinPoint joinPoint){
        /**
         * 获取第一个参数
         */
        try {
            Integer id = (Integer) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                //删除缓存
                CACHE_CONTAINER.remove(CACHE_DEPT_PROFIX+id);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }


    /**
     * 用户
     *声明切面表达式
     */
    private static final String POINTCUT_USER_UPDATE = "execution(* cn.jcet.module.sys.service.impl.UserServiceImpl.updateById(..))";
    private static final String POINTCUT_USER_ADD = "execution(* cn.jcet.module.sys.service.impl.UserServiceImpl.save(..))";
    private static final String POINTCUT_USER_GET = "execution(* cn.jcet.module.sys.service.impl.UserServiceImpl.getById(..))";
    private static final String POINTCUT_USER_DELETE = "execution(* cn.jcet.module.sys.service.impl.UserServiceImpl.removeById(..))";

    private static final String CACHE_USER_PROFIX = "user:";


    /**
     * 添加
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_USER_ADD)
    public Object cacheUserAdd(ProceedingJoinPoint joinPoint){
        try {
            User user = (User) joinPoint.getArgs()[0];
            Boolean result = (Boolean) joinPoint.proceed();
            if(result){
                CACHE_CONTAINER.put(CACHE_USER_PROFIX+user.getId(),user);
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 更新
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_USER_UPDATE)
    public Object cacheUserUpdate(ProceedingJoinPoint joinPoint){
        try {
            UserVo object = (UserVo) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                User user = (User) CACHE_CONTAINER.get(CACHE_USER_PROFIX + object.getId());
                if( null == user){
                    user = new User();
                }
                BeanUtils.copyProperties(object,user);
                //log.info("用户对象缓存已更新" + CACHE_USER_PROFIX + object.getId());
                CACHE_CONTAINER.put(CACHE_USER_PROFIX+user.getId(),user);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 获取
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_USER_GET)
    public Object cacheUserGet(ProceedingJoinPoint joinPoint){
        try {
            Integer object = (Integer) joinPoint.getArgs()[0];
            //从缓存中获取
            Object result1 = CACHE_CONTAINER.get(CACHE_USER_PROFIX + object);
            if (result1 != null) {
                return result1;
            } else {
                User result2 = (User) joinPoint.proceed();
                CACHE_CONTAINER.put(CACHE_USER_PROFIX+result2.getId(),result2);
                //log.info("未从缓存里面找到用户对象，去数据库查询并放到缓存"+CACHE_USER_PROFIX+result2.getId());
                return result2;
            }
        }catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    /**
     * 删除
     * @param joinPoint
     * @return
     */
    @Around(value = POINTCUT_USER_DELETE)
    public Object cacheUserDelete(ProceedingJoinPoint joinPoint){
        try {
            Integer id  = (Integer) joinPoint.getArgs()[0];
            Boolean isSuccess = (Boolean) joinPoint.proceed();
            if(isSuccess){
                CACHE_CONTAINER.remove(CACHE_USER_PROFIX+id);
                //log.info("用户对象缓存已删除"+CACHE_USER_PROFIX+id);
            }
            return isSuccess;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }
}